package com.onpositive.wiki3.db.impl;

import java.util.HashMap;
import java.util.HashSet;

import com.carrotsearch.hppc.IntOpenHashSet;
import com.onpositive.wiki3.db.ITitleMapper;
import com.onpositive.wiki3.db.IWikiDB;
import com.onpositive.wiki3.db.impl.CategoryRefMap.CatInf;

public class CategoryGraphReducer {

	IWikiDB db;
	private ITitleMapper titleMapper;

	public CategoryGraphReducer(IWikiDB db) {
		super();
		this.db = db;
		titleMapper = db.getTitleMapper();

		CategoryAccessImpl categoryAccessor = (CategoryAccessImpl) db
				.getCategoryAccessor();
		HashMap<Integer, CatInf> buildInfoMap = categoryAccessor.buildInfoMap();

		preRemove(buildInfoMap, "Hidden_categories");
		preRemove(buildInfoMap, "Container categories");
		optimize(buildInfoMap);

	}

	protected void preRemove(HashMap<Integer, CatInf> buildInfoMap, String title) {
		int id = titleMapper.getId(title);
		CatInf catInf = buildInfoMap.get(id);
		if (catInf != null && catInf.cats != null) {
			for (int q : catInf.cats.toArray()) {
				buildInfoMap.remove(q);
			}
		}
	}

	private void optimize(HashMap<Integer, CatInf> buildInfoMap) {
		System.out.println(buildInfoMap.size());
		HashMap<Integer, CatInf> toMove = new HashMap<Integer, CategoryRefMap.CatInf>();
		while (true) {
			for (CatInf i : buildInfoMap.values()) {
				if (i.cats != null) {
					guessRemovableChilds(toMove, i, buildInfoMap);
				}
				// int iz = findParentCat(i, buildInfoMap);
				// if (iz != -1) {
				// toMove.put(iz, i);
				// }

			}

			if (!toMove.isEmpty()) {
				IntOpenHashSet staleChildren = new IntOpenHashSet();
				for (Integer t : toMove.keySet()) {
					CatInf catInf = buildInfoMap.get(t);

					CatInf movedChildren = toMove.get(t);
					// System.out.println(titleMapper.getTitle(movedChildren.id));
					if (catInf != null) {
						if (catInf.cats == null) {
							System.out.println(titleMapper.getTitle(catInf.id));
							catInf.cats = new IntOpenHashSet();
						}
						catInf.cats.addAll(movedChildren.cats);
					}

					buildInfoMap.remove(movedChildren.id);
					staleChildren.add(movedChildren.id);
				}

				for (CatInf i : buildInfoMap.values()) {
					if (i.cats != null) {
						i.cats.removeAll(staleChildren);
					}
				}
				System.out.println(buildInfoMap.size());
				toMove = new HashMap<Integer, CategoryRefMap.CatInf>();
			} else {
				break;
			}
		}
		System.out.println(toMove);
	}

	static HashSet<String> remove = new HashSet<String>();

	static {
		remove.add("wikipedia");
		remove.add("talk");
		remove.add("categories_by_type");
		remove.add("template"); // Container_categories stub category
		remove.add("container_categories");
		remove.add("stub category");
	}

	private void guessRemovableChilds(HashMap<Integer, CatInf> toMove,
			CatInf i, HashMap<Integer, CatInf> buildInfoMap) {
		String title = titleMapper.getTitle(i.id);
		for (String s : remove) {
			if (title.toLowerCase().contains(s)) {
				toMove.put(-i.id, i);
			}
		}
		IntOpenHashSet m = new IntOpenHashSet();
		grabChidrens(i, i, m, buildInfoMap);
	}

	private void grabChidrens(CatInf root, CatInf i, IntOpenHashSet m,
			HashMap<Integer, CatInf> buildInfoMap) {
		if (i.cats != null) {
			for (int q : i.cats.toArray()) {
				String title = titleMapper.getTitle(q);
				title = title.toLowerCase().replace(' ', '_');
				if (title.endsWith("by_country") || title.equals("by_author")) {
					CatInf catInf = buildInfoMap.get(q);
					if (catInf != null) {
						if (catInf.cats != null) {
							for (int z : catInf.cats.toArray()) {
								CatInf catInf2 = buildInfoMap.get(z);
								if (catInf2!=null){
								buildInfoMap.put(root.id, catInf2);
								}
							}
						}
						buildInfoMap.put(root.id, catInf);
					}
				}
			}
		}
	}

}
